package ali

import (
	"encoding/json"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/go-playground/validator/v10"
	"github.com/pkg/errors"
)

// SmsConfig 阿里云短信 SDK 配置信息
type SmsConfig struct {
	SignName        string `json:"sign_name" validate:"required"`
	RegionId        string `json:"region_id" validate:"required"`
	AccessKeyId     string `json:"access_key_id" validate:"required"`
	AccessKeySecret string `json:"access_key_secret" validate:"required"`
}

// SmsHandler Sms 操作助手
type SmsHandler struct {
	Client   *sdk.Client
	SignName string
	RegionId string
}

// SmsRequest 阿里云短信发送请求参数接口体
type SmsRequest struct {
	Message   string
	RequestId string
	BizId     string
	Code      string
}

// SmsResponse 阿里云返回的json信息对应的结构体
type SmsResponse struct {
	Message   string
	RequestId string
	BizId     string
	Code      string
}

// BuildClient 构建 Sms 操作助手
func BuildSmsHandler(c *SmsConfig) (*SmsHandler, error) {
	// 1. 校验配置信息
	if err := validator.New().Struct(c); err != nil {
		return nil, errors.Cause(err)
	}
	// 2. 构建客户端
	client, err := sdk.NewClientWithAccessKey(c.RegionId, c.AccessKeyId, c.AccessKeySecret)
	if err != nil {
		return nil, errors.Cause(err)
	}
	// 3. 返回操作助手
	return &SmsHandler{Client: client, SignName: c.SignName, RegionId: c.RegionId}, nil
}

// SendCode 发送短信验证码
func (h *SmsHandler) SendCode(phone, code, templateCode string) error {
	// 1. 判断发送助手是否有效
	if h == nil || h.Client == nil {
		return errors.New("ali sms handler is abnormal")
	}
	// 2. 构建请求参数
	request := requests.NewCommonRequest()                           // 构造一个公共请求
	request.Method = "POST"                                          // 设置请求方式
	request.Product = "Ecs"                                          // 指定产品
	request.Scheme = "https"                                         // https | http
	request.Domain = "dysmsapi.aliyuncs.com"                         // 指定域名则不会寻址，如认证方式为 Bearer Token 的服务则需要指定
	request.Version = "2017-05-25"                                   // 指定产品版本
	request.ApiName = "SendSms"                                      // 指定接口名
	request.QueryParams["RegionId"] = h.RegionId                     // 阿里云地区配置信息
	request.QueryParams["SignName"] = h.SignName                     // 阿里云验证过的项目名，自己设置
	request.QueryParams["TemplateCode"] = templateCode               // 阿里云的短信模板号，自己设置
	request.QueryParams["TemplateParam"] = "{\"code\":" + code + "}" // 短信模板中的验证码内容，自己生成
	request.QueryParams["PhoneNumbers"] = phone                      // 发送目标手机号
	// 3. 发出短信请求
	res, err := h.Client.ProcessCommonRequest(request)
	if err != nil {
		return errors.WithStack(err)
	}
	// 4. 接收响应参数
	var message SmsResponse
	if err := json.Unmarshal(res.GetHttpContentBytes(), &message); err != nil {
		return errors.WithStack(err)
	}
	if message.Message != "OK" {
		return errors.New("ali sms send abnormal，" + message.Message)
	}
	return nil
}
